package com.ruoyi.config.util.gaode;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.check.CheckEmptyUtil;
import com.ruoyi.config.mapper.DictConfigMapper;
import com.ruoyi.config.util.address.AddressUtil;
import com.ruoyi.config.util.address.WSSsdrAddress;
import com.ruoyi.config.util.gaode.eunm.GeoCodeUrlEnum;
import com.ruoyi.config.util.gaode.eunm.ReGeoCodeUrlEnum;
import com.ruoyi.config.util.gaode.vo.GeoCodeVO;
import com.ruoyi.config.util.gaode.vo.ReGeoCodeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 *
 */
@Component
@Slf4j
public class GaoDeUtil {

//    private static final String GAO_DE_KEY = "627593036771a910fbf20e666a683ffc";

    @Resource
    public RestTemplate restTemplate;
    @Resource
    private DictConfigMapper dictConfigMapper;
    // 申请的账户Key

    /**
     * 功能描述: 根据地址名称得到两个地址间的距离
     *
     * @param start 起始位置
     * @param end   结束位置
     * @return long 两个地址间的距离(单位:米)
     */
    public Long getDistanceByAddress(String start, String end) {
        String startLonLat = geoCode(start);
        String endLonLat = geoCode(end);
        Long distance = getDistance(startLonLat, endLonLat);
        return distance;
    }

    /**
     * @param address 地址
     * @return location 经纬度
     * @Description 根据地址转化为经纬度
     */
    public String geoCode(String address) {
        String gaoDeKey = dictConfigMapper.getGaoDeKey();
        GeoCodeVO geoCodeVO = restTemplate.getForObject(String.format(GeoCodeUrlEnum.GEO_CODE.getRoutePlanURL(), gaoDeKey, address), GeoCodeVO.class);
        if (CheckEmptyUtil.isEmpty(geoCodeVO) || CheckEmptyUtil.isEmpty(geoCodeVO.getGeocodes().get(0).getLocation())) {
            throw new RuntimeException("参数错误");
        }
        String location = geoCodeVO.getGeocodes().get(0).getLocation();
        log.info("地理编码：地址：[{}],返回的经纬度：[{}]", address, location);
        return location;
    }


    /**
     * @param location 经纬度
     * @return address 地址
     * @Description 根据经纬度转化为地址
     */
    public String ReGeoCode(String location) {
        String gaoDeKey = dictConfigMapper.getGaoDeKey();
        ReGeoCodeVO reGeoCodeVO = restTemplate.getForObject(String.format(ReGeoCodeUrlEnum.RE_GEO_CODE.getRoutePlanURL(), gaoDeKey, location), ReGeoCodeVO.class);
        if (CheckEmptyUtil.isEmpty(reGeoCodeVO) || CheckEmptyUtil.isEmpty(reGeoCodeVO.getRegeocode().getFormattedAddress())) {
            throw new RuntimeException("参数错误");
        }
        String address = reGeoCodeVO.getRegeocode().getFormattedAddress();
        String city = reGeoCodeVO.getRegeocode().getAddressComponent().getCity().toString();
        String province = (String) reGeoCodeVO.getRegeocode().getAddressComponent().getProvince();
        log.info("逆地理编码：经纬度：[{}],返回的地址：[{}],省份:{},市区:{}", location, address, province, city);
        return address;
    }


    public String getTownship(String location) {
        String gaoDeKey = dictConfigMapper.getGaoDeKey();
        ReGeoCodeVO reGeoCodeVO = restTemplate.getForObject(String.format(ReGeoCodeUrlEnum.RE_GEO_CODE.getRoutePlanURL(),gaoDeKey, location), ReGeoCodeVO.class);
        if (CheckEmptyUtil.isEmpty(reGeoCodeVO) || CheckEmptyUtil.isEmpty(reGeoCodeVO.getRegeocode().getFormattedAddress())) {
            throw new RuntimeException("参数错误");
        }
        String address = reGeoCodeVO.getRegeocode().getFormattedAddress();
        String city = reGeoCodeVO.getRegeocode().getAddressComponent().getCity().toString();
        String province = (String) reGeoCodeVO.getRegeocode().getAddressComponent().getProvince();
        String township = (String) reGeoCodeVO.getRegeocode().getAddressComponent().getTownship();
        log.info("逆地理编码：经纬度：[{}],返回的地址：[{}],省份:{},市区:{},街道:{}", location, address, province, city, township);
        return township;
    }

    public String GaoGetTownship(String location) {
        String gaoDeKey = dictConfigMapper.getGaoDeKey();
        ReGeoCodeVO reGeoCodeVO = restTemplate.getForObject(String.format(ReGeoCodeUrlEnum.RE_GEO_CODE.getRoutePlanURL(), gaoDeKey, location), ReGeoCodeVO.class);
        if (CheckEmptyUtil.isEmpty(reGeoCodeVO) || CheckEmptyUtil.isEmpty(reGeoCodeVO.getRegeocode().getFormattedAddress())) {
            throw new RuntimeException("参数错误");
        }
        String address = reGeoCodeVO.getRegeocode().getFormattedAddress();

        WSSsdrAddress add = AddressUtil.addressFormat(address);
        return CheckEmptyUtil.isEmpty(add.getVillage()) ? add.getTown() : add.getVillage();
    }

    /**
     * 功能描述: 根据两个定位点的经纬度算出两点间的距离
     *
     * @param startLonLat 起始经纬度
     * @param endLonLat   结束经纬度（目标经纬度）
     * @return java.lang.Long 两个定位点之间的距离 单位：米
     */
    public Long getDistance(String startLonLat, String endLonLat) {
        try {
            String gaoDeKey = dictConfigMapper.getGaoDeKey();
            // 返回起始地startAddr与目的地endAddr之间的距离，单位：米
            Long result = new Long(0);
            String queryUrl = "http://restapi.amap.com/v3/distance?key=" + gaoDeKey + "&origins=" + startLonLat + "&destination=" + endLonLat;
            String queryResult = getResponse(queryUrl);
            JSONObject job = JSONObject.parseObject(queryResult);
            JSONArray ja = job.getJSONArray("results");
            JSONObject jobO = JSONObject.parseObject(ja.getString(0));
            result = Long.parseLong(jobO.get("distance").toString());
            log.info("距离：" + result);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("系统错误:" + e.getMessage());
        }


    }

    /**
     * 功能描述: 发送请求
     *
     * @param serverUrl 请求地址
     * @return java.lang.String
     */
    private static String getResponse(String serverUrl) {
        // 用JAVA发起http请求，并返回json格式的结果
        StringBuffer result = new StringBuffer();
        try {
            URL url = new URL(serverUrl);
            URLConnection conn = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            in.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result.toString();
    }

}